#ifndef __BASE_H__
#define __BASE_H__
#include "meshcomm.h"
#include "enumerations.h"
#include "constants.h"
#include "element.h"
// 定义适合于一、二、三维的基函数的原型 ([x,y,z],[xi,eta,zeta])
typedef void BASEFUNCTION(ELEMENT *, double[], double[], double *);
// 定义适合于一、二、三维的泛函原型
typedef void NODALFUNCTION(ELEMENT *, FUNCTIONVEC, INT, double *);

/** define a type of struct to describe the base functions */
typedef struct BASE_
{
    INT worlddim;
    // the number of the base functions, 基函数中包括函数的个数
    INT NumBase;
    // the dimension of the value for each base function
    // 基函数中函数值的维数，Lagrang型基函数的维数是1，向量函数的维数等于空间维数
    INT ValueDim;
    //hhxie添加 2023-02-16
    // the dimension of the interpolation value for each base function
    // 有限元基函数的插值值的维数,比如弹性基函数一般来说等于ValueDim, Maxwell方程的插值条件是面上的法向分量,那么这个维数等于1
    INT InterpolationValueDim;
    // the polynomial degree in the base functions
    // 基函数中的多项式的阶数
    INT PolynomialDegree;
    // lhc添加
    // 基函数的函数及导数取值是否都只依赖于RefCoord 完全不依赖于Coord
    BOOL IsOnlyDependOnRefCoord;
    // the accuracy of the element
    // 基函数求解有限元的精度阶数，实际作用不是很大
    INT Accuracy;
    // define the type of element: Invariant=1 means the element
    // is invariant under the affine transform, Invariant=0 means the
    // element is defined on the actual element
    // bool Invariant;
    // the maptype: Affine means we have the invariant according to the affine map
    // Piola: another type of mapping used in the H(div) and H(curl)
    // Actual: mans we can not use tha mapping in the matrix building process
    MAPTYPE MapType;
    // the distribution of the degree of freedom:
    // DOF[0]: the dof on the vertices
    // DOF[1]: the dof on the lines
    // DOF[2]: the dof on the face
    // DOF[3]: the dof on the volume 
    INT DOF[4];
    // the corresponding based finctions: [D00,D10,D01,D20,D11,D02]
    // 一维的时候提供相对于[D0,D1,D2]的基函数,3个基函数
    // 二维的时候提供相对于[D00,D10,D01,D20,D02,D11]的基函数,6个基函数
    // 三维的时候提供相对于[D000,D100,D010,D001,D200,D020,D002,D110,D101,D011]的基函数,10个基函数
    INT NMultiIndices; //一维的时候为3，二维的时候为6，三维的时候为10
    // 下面定义具体的基函数集合，里面包含的基函数个数等于NMultiIndices
    BASEFUNCTION **BaseFun;
    // the corresponding nodal function: always needed for INTerpolation
    NODALFUNCTION *NodalFun;
    // 插值函数的定义，主要是用来生成多重网格算法中的插值矩阵
    FUNCTIONVEC *InterFun;
    // some seriers for save temp values
    double *Values_X;
    double *Values_Y;
    double *Values_XY;
    double *Values_Z;
    double *Values_XZ;
    double *Values_YZ;
} BASE;

//下面是用来组装具体的基函数的程序
// 建立一维的有限元基函数
BASE *Base1DBuild(INT num_bas, INT value_dim, INT inter_dim, INT polydeg,
                  BOOL IsOnlyDependOnRefCoord, INT accuracy, MAPTYPE MapType, INT *dof,
                  BASEFUNCTION *baseD0, BASEFUNCTION *baseD1,
                  BASEFUNCTION *baseD2, NODALFUNCTION *NodalFun, FUNCTIONVEC *InterFun);
// 建立二维的有限元基函数
BASE *BaseBuild2D(INT num_bas, INT value_dim, INT inter_dim, INT polydeg,
                  BOOL IsOnlyDependOnRefCoord, INT accuracy, MAPTYPE MapType, INT *dof,
                  BASEFUNCTION *baseD00, BASEFUNCTION *baseD10,
                  BASEFUNCTION *baseD01, BASEFUNCTION *baseD20,
                  BASEFUNCTION *baseD11, BASEFUNCTION *baseD02,
                  NODALFUNCTION *NodalFun, FUNCTIONVEC *InterFun);
// 建立三维的有限元基函数
BASE *BaseBuild3D(INT num_bas, INT value_dim, INT inter_dim, INT polydeg,
                  BOOL IsOnlyDependOnRefCoord, INT accuracy, MAPTYPE MapType, INT *dof,
                  BASEFUNCTION *baseD000, BASEFUNCTION *baseD100,
                  BASEFUNCTION *baseD010, BASEFUNCTION *baseD001,
                  BASEFUNCTION *baseD200, BASEFUNCTION *baseD020,
                  BASEFUNCTION *baseD002, BASEFUNCTION *baseD110,
                  BASEFUNCTION *baseD101, BASEFUNCTION *baseD011,
                  NODALFUNCTION *NodalFun, FUNCTIONVEC *InterFun);
//根据基函数求解相应的基函数值
void GetBaseValues(BASE *Base, MULTIINDEX MultiIndex,
                   ELEMENT *EElem, double Coord[],
                   double RefCoord[], double *Values);
void BaseDestroy(BASE **Base);
#endif